package com.example.springsecuritydemo.config;

import com.example.springsecuritydemo.entity.User;
import com.example.springsecuritydemo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsPasswordService;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.UserDetailsManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
/**
 * 基于数据库的自定义用户管理器
 *
 * 通过 @Bean 方式由配置类注册到 Spring 容器
 */
/**
 * UserDetailsService 是一个接口，用于获取用户信息。这是Spring Security认证体系中的核心组件，
 * 负责根据用户名加载用户详情，为认证过程提供必要的用户数据。
 * <p>
 * 此实现使用DBUserDetailsManager从数据库获取用户信息
 *
 * @return UserDetailsService实例，用于Spring Security认证过程
 */
@Component
public class DBUserDetailsManager implements UserDetailsManager, UserDetailsPasswordService {
    //UserDetailsManager继承了UserDetailsService
    @Resource
    private UserMapper userMapper;
    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails updatePassword(UserDetails user, String newPassword) {
        // 更新用户密码
        User userEntity = userMapper.findByUsername(user.getUsername());
        if (userEntity != null) {
            userEntity.setPassword(newPassword);
            userMapper.update(userEntity);
            
            // 返回更新后的UserDetails对象
            return org.springframework.security.core.userdetails.User.builder()
                    .username(user.getUsername())
                    .password(newPassword)
                    .authorities(user.getAuthorities())
                    .build();
        }
        return user;
    }

    @Override
    @Transactional
    public void createUser(UserDetails userDetails) {
        // 创建新用户
        User user = new User();
        user.setUsername(userDetails.getUsername());
        user.setPassword(passwordEncoder.encode(userDetails.getPassword()));
        user.setEnabled(true);
        userMapper.insert(user);
    }

    @Override
    @Transactional
    public void updateUser(UserDetails userDetails) {
        // 更新用户信息
        User user = userMapper.findByUsername(userDetails.getUsername());
        if (user != null) {
            user.setUsername(userDetails.getUsername());
            user.setPassword(passwordEncoder.encode(userDetails.getPassword()));
            user.setEnabled(userDetails.isEnabled());
            userMapper.update(user);
        }
    }

    @Override
    @Transactional
    public void deleteUser(String username) {
        // 删除用户
        User userEntity = userMapper.findByUsername(username);
        if (userEntity != null) {
            userMapper.deleteById(userEntity.getId());
        }
    }

    @Override
    @Transactional
    public void changePassword(String oldPassword, String newPassword) {
        // 注意：此方法在实际应用中通常需要当前认证用户的用户名
        // 这里简化处理，实际项目中应通过Authentication获取当前用户
    }

    @Override
    public boolean userExists(String username) {
        User user = userMapper.findByUsername(username);
        return user != null;
    }

    /**
     * 根据用户名加载用户详细信息
     *
     * @param username 要查找的用户标识符
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username + "用户不存在");
        } else {
             /*
            //创建一个权限列表
            Collection<GrantedAuthority> authorities = new ArrayList<>();
            authorities.add(() -> "USER_SELECT");
           return new org.springframework.security.core.userdetails.User(
                    user.getUsername(),  // 设置用户名
                    user.getPassword(),  // 设置用户密码
                    user.getEnabled(),   // 设置用户是否启用
                    true,                // 设置账户是否未过期
                    true,                // 设置凭证是否未过期
                    true,                // 设置账户是否未锁定
                    authorities          // 设置用户的权限集合
            );*/

            //关于角色的授权
            return org.springframework.security.core.userdetails.User
                    .withUsername(user.getUsername())
                    .password(user.getPassword())
                    .disabled(!user.getEnabled())
                    .credentialsExpired( false)
                    .accountExpired(false)
                    .roles("USER")
                    .authorities("INDEX")
                    .build();
        }
    }
}